const UNIT_ERROR = 'error';
const UNIT_CONSTANT = 'i';
const UNIT_DIVIDER = '*';

/**
 * 获取单位信息
 * @param unit - 单位
 * @returns {{top: string, bottom: string}}
 */
const getUnitInfo = unit => {
    if (!unit) {
        return { top: UNIT_CONSTANT, bottom: UNIT_CONSTANT };
    }
    const [top = UNIT_CONSTANT, bottom = UNIT_CONSTANT] = unit.split('/');

    return { top, bottom };
};

/**
 * 判断单位是否相等，例如：单位"分*时"与"时*分"是相等的
 * @param unit1
 * @param unit2
 * @returns {boolean}
 */
const unitIsEqual = (unit1, unit2) => {
    if (unit1 === unit2) {
        return true;
    }

    const unit1Info = getUnitInfo(unit1);
    const unit1TopStr = unit1Info.top
        .split(UNIT_DIVIDER)
        .sort()
        .join(UNIT_DIVIDER);
    const unit1BottomStr = unit1Info.bottom
        .split(UNIT_DIVIDER)
        .sort()
        .join(UNIT_DIVIDER);

    const unit2Info = getUnitInfo(unit2);
    const unit2TopStr = unit2Info.top
        .split(UNIT_DIVIDER)
        .sort()
        .join(UNIT_DIVIDER);
    const unit2BottomStr = unit2Info.bottom
        .split(UNIT_DIVIDER)
        .sort()
        .join(UNIT_DIVIDER);

    return unit1TopStr === unit2TopStr && unit1BottomStr === unit2BottomStr;
};

/**
 * 分子单位与分母单位
 * @param topUnit
 * @param bottomUnit
 * @returns {string}
 */
const mergeUnit = (topUnit, bottomUnit) => {
    let tempTopUnit;
    let tempBottomUnit;
    let needAddToResult;
    const resultUnitArray = [];
    const newTopUnit = topUnit || UNIT_CONSTANT;
    const newBottomUnit = bottomUnit || UNIT_CONSTANT;

    const newTopArray = newTopUnit.split(UNIT_DIVIDER).filter(unit => unit !== UNIT_CONSTANT);
    const newBottomArray = newBottomUnit.split(UNIT_DIVIDER).filter(unit => unit !== UNIT_CONSTANT);

    for (let i = 0, { length } = newTopArray; i < length; i += 1) {
        needAddToResult = true;
        tempTopUnit = newTopArray[i];

        for (let j = 0, { length: len } = newBottomArray; j < len; j += 1) {
            tempBottomUnit = newBottomArray[j];

            // 单位相同时，消掉该单位
            if (tempTopUnit === tempBottomUnit) {
                needAddToResult = false;
                newBottomArray.splice(j, 1);
                break;
            }
        }

        if (needAddToResult) {
            resultUnitArray.push(tempTopUnit);
        }
    }

    if (newBottomArray.length === 0 && resultUnitArray.length === 0) {
        return UNIT_CONSTANT;
    }

    if (newBottomArray.length === 0) {
        return resultUnitArray.join(UNIT_DIVIDER);
    }

    if (resultUnitArray.length === 0) {
        return `${UNIT_CONSTANT}/${newBottomArray.join(UNIT_DIVIDER)}`;
    }

    return `${resultUnitArray.join(UNIT_DIVIDER)}/${newBottomArray.join(UNIT_DIVIDER)}`;
};

/**
 * 单位相加
 * @param unit1 - 单位1
 * @param unit2 - 单位2
 * @returns {string|*}
 */
const unitAdd = (unit1, unit2) => {
    const u1 = unit1 || UNIT_CONSTANT;
    const u2 = unit2 || UNIT_CONSTANT;

    if (u1 === UNIT_ERROR || u2 === UNIT_ERROR) {
        return UNIT_ERROR;
    }

    if (u1 === u2) {
        return u1;
    }

    if (u1 === UNIT_CONSTANT && u2 !== UNIT_CONSTANT) {
        return unit2;
    }

    if (u1 !== UNIT_CONSTANT && u2 === UNIT_CONSTANT) {
        return unit1;
    }

    if (unitIsEqual(u1, u2)) {
        return u1;
    }

    return UNIT_ERROR;
};

/**
 * 单位相乘
 * @param unit1 - 单位1
 * @param unit2 - 单位2
 * @returns {string}
 */
const unitMultiply = (unit1, unit2) => {
    const u1 = unit1 || UNIT_CONSTANT;
    const u2 = unit2 || UNIT_CONSTANT;

    if (u1 === UNIT_ERROR || u2 === UNIT_ERROR) {
        return UNIT_ERROR;
    }

    if (unit1 === UNIT_CONSTANT && unit2 === UNIT_CONSTANT) {
        return UNIT_CONSTANT;
    }

    const { top: u1Top, bottom: u1Bottom } = getUnitInfo(u1);
    const { top: u2Top, bottom: u2Bottom } = getUnitInfo(u2);

    const newTop = u1Top && u2Top ? `${u1Top}${UNIT_DIVIDER}${u2Top}` : `${u1Top}${u2Top}`;
    const newBottom = u1Bottom && u2Bottom ? `${u1Bottom}${UNIT_DIVIDER}${u2Bottom}` : `${u1Bottom}${u2Bottom}`;

    return mergeUnit(newTop, newBottom);
};

/**
 * 单位相除
 * @param unit1 - 单位1
 * @param unit2 - 单位2
 */
const unitDivide = (unit1, unit2) => {
    const u1 = unit1 || UNIT_CONSTANT;
    const u2 = unit2 || UNIT_CONSTANT;

    if (u1 === UNIT_ERROR || u2 === UNIT_ERROR) {
        return UNIT_ERROR;
    }

    if (unit1 === UNIT_CONSTANT && unit2 === UNIT_CONSTANT) {
        return UNIT_CONSTANT;
    }

    const { top: u1Top, bottom: u1Bottom } = getUnitInfo(u1);
    const { top: u2Top, bottom: u2Bottom } = getUnitInfo(u2);

    const newTop = u1Top && u2Bottom ? `${u1Top}${UNIT_DIVIDER}${u2Bottom}` : `${u1Top}${u2Bottom}`;
    const newBottom = u1Bottom && u2Top ? `${u1Bottom}${UNIT_DIVIDER}${u2Top}` : `${u1Bottom}${u2Top}`;

    return mergeUnit(newTop, newBottom);
};

const UNIT = {
    ERROR: UNIT_ERROR,
    CONSTANT: UNIT_CONSTANT,
    MONEY: '$'
};
export { unitAdd, unitAdd as unitMinus, unitMultiply, unitDivide, UNIT };
